<template>
  <div id="app">
    <el-upload
      drag
      action
      :auto-upload="false"
      :show-file-list="false"
      :on-change="changeFile"
    >
      <i class="el-icon-upload"></i>
      <div class="el-upload__text">
        将文件拖到此处，或
        <em>点击上传app3</em>
      </div>
    </el-upload>

    <!-- PROGRESS -->
    <div class="progress">
      <span>上传进度：{{ total | totalText }}%</span>
      <el-link
        type="primary"
        v-if="total > 0 && total < 100"
        @click="handleBtn"
        >{{ btn | btnText }}</el-link
      >
    </div>

    
  </div>
</template>

<script>
import { fileParse } from "./assets/utils";
// import axios from "axios";
import SparkMD5 from "spark-md5";

export default {
  // name: "App",
  data() {
    return {
      total: 0,
      video: null,
      btn: false,
      mergeFileName: null, // 发送合并请求传的参数
      fileSize: null, // 文件总大小
      startNum: 0, //断点续传从第几个开始传
      myEnd: true, //自定义暂停
      myEndNum: 0, //自定义暂停的计数器
    };
  },
  filters: {
    btnText(btn) {
      return btn ? "继续" : "暂停";
    },
    totalText(total) {
      return total > 100 ? 100 : total;
    },
  },
  methods: {
    async changeFile(file) {
      this.mergeFileName = file.name;
      this.fileSize = file.size;
      if (!file) return;
      file = file.raw;

      // 解析为BUFFER数据
      // 我们会把文件切片处理：把一个文件分割成为好几个部分（固定数量/固定大小）
      // 每一个切片有自己的部分数据和自己的名字
      // HASH.mp4-1
      // HASH.mp4-2
      // ...
      let buffer = await fileParse(file, "buffer"),
        spark = new SparkMD5.ArrayBuffer(),
        hash;
      // suffix;//后缀
      spark.append(buffer);
      hash = spark.end();
      // suffix = /\.([0-9a-zA-Z]+)$/i.exec(file.name)[1];

      // 1先发请求，传入参数，1文件大小，2文件md5
      let _this = this;
      axios
        .get("http://127.0.0.1:11230/verify", {
          params: {
            fileSize: file.size,
            md5: hash,
            fileName: file.name,
          },
        })
        .then(function (resp) {
          // 返回2表示断点续传，从第num个开始上传
          if (resp.data.code == 2) {
            console.log("resp.num的值为");
            console.log(resp.data.num);
            _this.startNum = resp.data.num;
            console.log(_this.startNum);
          }

          // 创建100个切片
          let partList = [],
            partsize = 1024 * 1024,
            num = Math.ceil(file.size / (1024 * 1024)),
            cur = 0;
          for (let i = 1; i <= num; i++) {
            if (i == num) {
              partsize = file.size - 1024 * 1024 * (num - 1);
            }
            let item = {
              chunk: file.slice(cur, cur + partsize),
              // filename: file.name.split('.')[0]+`-${i}.${suffix}`,
              filename: file.name + `-${i}`,
              sort: i,
              hash: hash,
              partsize: partsize,
            };
            cur += partsize;
            partList.push(item);
          }

          if (_this.startNum > 1) {
            for (let i = 0; i < _this.startNum - 1; i++) {
              partList.splice(0, 1);
            }
          }

          _this.partList = partList;
          _this.hash = hash;
          _this.sendRequest();
        });
      // 1end
    },

    async sendRequest() {
      let num = Math.ceil(this.fileSize / (1024 * 1024));
      // 断点续传的进度条，直接跳到续传的进度
      console.log("async sendRequest()方法");
      console.log(this.startNum);
      if (this.startNum > 1) {
        console.log("进入this.startNum > 1");
        this.total = (100 / num) * this.startNum + 0.1;
        console.log(this.startNum);
        this.startNum = 0;
      }
      console.log("断点进度");
      console.log(this.total);
      // 根据100个切片创造100个请求（集合）
      let requestList = [];
      this.partList.forEach((item, index) => {
        console.log(this.myEnd);
        if (!this.myEnd) {
          console.log("myEnd变为false");
          while (true) {
            if (this.myEnd) {
              break;
            }
          }
        }
        // 每一个函数都是发送一个切片的请求
        let fn = () => {
          let formData = new FormData();
          formData.append("file", item.chunk);
          formData.append("filename", item.filename);
          formData.append("sort", item.sort);
          formData.append("hash", item.hash);
          formData.append("partsize", item.partsize);
          return axios
            .post("http://127.0.0.1:11230/single3", formData, {
              headers: { "Content-Type": "multipart/form-data" },
            })
            .then((result) => {
              result = result.data;
              if (result.code == 0) {
                if (this.total == 0) {
                  //避免最后进度不到100
                  this.total = 0.1;
                }
                this.total += 100 / num;
                console.log(num);
                console.log(this.total);
                // 传完的切片我们把它移除掉
                this.partList.splice(index, 1);
              }
            });
        };
        requestList.push(fn); // 把所有请求放入list
      });

      // 传递：并行(ajax.abort())/串行(基于标志控制不发送)
      let i = 0; //记录传了多少
      let complete = async () => {
        let result = await axios.get("http://127.0.0.1:11230/v3merge", {
          params: {
            hash: this.hash,
            filename: this.mergeFileName,
          },
        });
        result = result.data;
        if (result.code == 0) {
          this.video = result.path;
        }
      };
      // let send = async () => {
      this.send = async () => {
        // 已经中断则不再上传
        if (this.abort) return;
        if (this.myEndNum >= requestList.length) {
          // 都传完了
          complete();
          return;
        }
        await requestList[this.myEndNum]();

        console.log(this.myEndNum);
        console.log(requestList);

        this.myEndNum++;
        this.send();
      };
      this.send();
    },

    handleBtn() {
      if (this.btn) {
        //断点续传
        this.abort = false;
        this.btn = false;
        // this.sendRequest();
        this.send();
        return;
      }
      //暂停上传
      this.btn = true;
      this.abort = true;
    },
  },
};
</script>
<style>
.progress {
    box-sizing: border-box;
    margin-top: 20px;
    padding: 0 10px;
    width: 360px;
    height: 50px;

    display: flex;
    justify-content: space-between;
    align-items: center;
    background: lightcyan;
}
#app {
    box-sizing: border-box;
    padding: 20px;
    height: 100vh;
}
</style>